package com.qjcc.util;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import com.qjcc.R;
import com.qjcc.app.AppContext;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.protocol.HTTP;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Android调用http请求
 * Created by WangKun on 2015/09/08.
 */
public class HttpAccessUtils{
    // 含有3个线程的线程池
	private static final String APPLICATION_JSON = "application/json; charset=utf-8";

	private static final String CONTENT_TYPE_TEXT_JSON = "text/json";
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
    public static final String UTF_8 = "UTF-8";
    private final static int TIMEOUT_CONNECTION = 20000;
	private final static int TIMEOUT_SOCKET = 20000;
	private final static int RETRY_TIME = 3;
	private final static int TOAST_TIP_TIME = 3000;
	private static String appCookie;
	private static String appUserAgent;
	private static String HOST = "";
	private static Context activityContext;
    //用户缓存信息
    private static String userSessionId;
    //http连接提示
    private static String MSG_CON_TIMEOUT = "";
    private static String MSG_CON_ERR = "";
    private static String MSG_RESQ_TIMEOUT = "";
    private static String MSG_NO_NETWORK = "";

	public static void init(Context context) {
		activityContext = context;
		HOST = context.getResources().getString(R.string.domain);
		MSG_CON_TIMEOUT = context.getResources().getString(R.string.msg_con_timeout);
		MSG_CON_ERR = context.getResources().getString(R.string.msg_con_err);
		MSG_RESQ_TIMEOUT = context.getResources().getString(R.string.msg_resq_timeout);
		MSG_NO_NETWORK = context.getResources().getString(R.string.msg_no_network);
	}

    /**
     * 访问指定url地址
     * @param url   指定待访问url地址
     * @param paramsMap    传入参数
     * @param httpAccessCallBack    回调接口
     * 如果请求服务成功则返回服务器数据，如果失败或有异常则返回{ok:false,msg:[具体原因]}
     */
    public static void callHttpAccess(Context context,final String url, Map<String, String> paramsMap, final HttpAccessCallBack httpAccessCallBack) {
    	userSessionId = SharedPreferencesUtil.getSessionId(context);
    	if(NetWorkUtil.isConnect(context)){//检查设备网络是否可用
    		// 添加传入参数
    		final List<NameValuePair> paramsList = new ArrayList<NameValuePair>();
    		if (null != paramsMap) {
    			for (Iterator<Map.Entry<String, String>> it = paramsMap.entrySet().iterator(); it.hasNext();) {
    				Map.Entry<String, String> entry = it.next();
    				paramsList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
    			}
    		}
    		// 用于子线程与主线程通信的Handler
    		final Handler mHandler = new Handler() {
    			@Override
    			public void handleMessage(Message msg) {
    				super.handleMessage(msg);
    				// 将返回值回调到callBack的参数中
    				httpAccessCallBack.callBack(msg.obj);
    			}

    		};

    		// 开启线程去访问http
    		executorService.submit(new Runnable() {
    			@Override
    			public void run() {
    				StringBuilder total = new StringBuilder();
    				HttpPost httpRequest = new HttpPost(url);
    				try {
    					httpRequest.setEntity(new UrlEncodedFormEntity(paramsList, HTTP.UTF_8));
    					//设置http头，以保持http请求session
    					if(userSessionId !=null ){
    						httpRequest.setHeader("Cookie", userSessionId);
    					}

    					DefaultHttpClient client = new DefaultHttpClient();
    	                // 请求超时
    	                client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, TIMEOUT_CONNECTION);
    	                // 读取超时
    	                client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, TIMEOUT_SOCKET);
    					HttpResponse httpResponse = client.execute(httpRequest);
    					if (httpResponse.getStatusLine().getStatusCode() == 200) {
    						String line = "";
    						BufferedReader rd = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
    						while ((line = rd.readLine()) != null) {
    							total.append(line);
    						}
    					}else{
        					total.append("{\"success\":false,\"msg\":\""+AppContext.getAppContext().getResources().getString(R.string.url_err)+"！："+url+AppContext.getAppContext().getResources().getString(R.string.err_code)+"："+httpResponse.getStatusLine().getStatusCode()+"\"}");
    						Log.i("HttpAccessUtils",AppContext.getAppContext().getResources().getString(R.string.url_err)+"！："+url);
    					}
    				}catch(ConnectTimeoutException e1){
    					total.append("{\"success\":false,\"msg\":\""+MSG_CON_TIMEOUT+"\"}");
    				}catch(InterruptedIOException e2){
    					total.append("{\"success\":false,\"msg\":\""+MSG_RESQ_TIMEOUT+"\"}");
    				}catch(ConnectException e3){
    					total.append("{\"success\":false,\"msg\":\""+MSG_CON_ERR+"\"}");
    				}catch (IOException e) {
    					total.append("{\"success\":false,\"msg\":\""+e.getLocalizedMessage()+"\"}");
    					Log.e("HttpAccessUtils", "IOException"+AppContext.getAppContext().getResources().getString(R.string.exception), e);
    				}finally {
    					// 将获取的消息利用Handler发送到主线程
    					mHandler.sendMessage(mHandler.obtainMessage(0, total));
    				}
    			}
    		});
    	}else{
    		UIHelper.ToastMessage(context, MSG_NO_NETWORK);
    	}
    }



	/**
	 * 访问指定url地址
	 * @param url   指定待访问url地址
	 * @param json    传入参数
	 * @param httpAccessCallBack    回调接口
	 * 如果请求服务成功则返回服务器数据，如果失败或有异常则返回{ok:false,msg:[具体原因]}
	 */
	public static void callHttpAccess4Json(Context context,final String url, final String json, final HttpAccessCallBack httpAccessCallBack) {
		userSessionId = SharedPreferencesUtil.getSessionId(context);
		if(NetWorkUtil.isConnect(context)){//检查设备网络是否可用

			// 用于子线程与主线程通信的Handler
			final Handler mHandler = new Handler() {
				@Override
				public void handleMessage(Message msg) {
					super.handleMessage(msg);
					// 将返回值回调到callBack的参数中
					httpAccessCallBack.callBack(msg.obj);
				}

			};

			// 开启线程去访问http
			executorService.submit(new Runnable() {
				@Override
				public void run() {
					StringBuilder total = new StringBuilder();
					HttpPost httpRequest = new HttpPost(url);
					httpRequest.addHeader(HTTP.CONTENT_TYPE, APPLICATION_JSON);

					try {
						//设置http头，以保持http请求session
						if(userSessionId !=null ){
							httpRequest.setHeader("Cookie", userSessionId);
						}

						BasicHttpParams httpParams = new BasicHttpParams();
						httpParams.setParameter("charset", "UTF-8");
						HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_CONNECTION);  //毫秒
						HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_SOCKET);
						DefaultHttpClient client = new DefaultHttpClient(httpParams);

						httpRequest.setEntity(new StringEntity(json.toString(),"UTF-8"));

						HttpResponse httpResponse = client.execute(httpRequest);
						if (httpResponse.getStatusLine().getStatusCode() == 200) {
							String line = "";
							BufferedReader rd = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
							while ((line = rd.readLine()) != null) {
								total.append(line);
							}
						}else{
							total.append("{\"success\":false,\"msg\":\""+AppContext.getAppContext().getResources().getString(R.string.url_err)+"！："+url+AppContext.getAppContext().getResources().getString(R.string.err_code)+"："+httpResponse.getStatusLine().getStatusCode()+"\"}");
							Log.i("HttpAccessUtils",AppContext.getAppContext().getResources().getString(R.string.url_err)+"！："+url);
						}
					}catch(ConnectTimeoutException e1){
						total.append("{\"success\":false,\"msg\":\""+MSG_CON_TIMEOUT+"\"}");
					}catch(InterruptedIOException e2){
						total.append("{\"success\":false,\"msg\":\""+MSG_RESQ_TIMEOUT+"\"}");
					}catch(ConnectException e3){
						total.append("{\"success\":false,\"msg\":\""+MSG_CON_ERR+"\"}");
					}catch (IOException e) {
						total.append("{\"success\":false,\"msg\":\""+e.getLocalizedMessage()+"\"}");
						Log.e("HttpAccessUtils", "IOException"+AppContext.getAppContext().getResources().getString(R.string.exception), e);
					}finally {
						// 将获取的消息利用Handler发送到主线程
						mHandler.sendMessage(mHandler.obtainMessage(0, total));
					}
				}
			});
		}else{
			UIHelper.ToastMessage(context, MSG_NO_NETWORK);
		}
	}
    /**
     * 定义返回接口
     */
    public interface HttpAccessCallBack {
        void callBack(Object result);
    }

    public static void cleanCookie() {
		appCookie = "";
	}

	private static String getUserAgent(AppContext appContext) {
		if(appUserAgent == null || appUserAgent == "") {
			StringBuilder ua = new StringBuilder("SCTF");
			ua.append('/'+appContext.getPackageInfo().versionName+'_'+appContext.getPackageInfo().versionCode);//App版本
			ua.append("/Android");//手机系统平台
			ua.append("/"+android.os.Build.VERSION.RELEASE);//手机系统版本
			ua.append("/"+android.os.Build.MODEL); //手机型号
//			ua.append("/"+appContext.getAppId());//客户端唯一标识
			appUserAgent = ua.toString();
		}
		return appUserAgent;
	}

	private static HttpClient getHttpClient() {
        HttpClient httpClient = new HttpClient();
		// 设置 HttpClient 接收 Cookie,用与浏览器一样的策略
		httpClient.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
        // 设置 默认的超时重试处理策略
		httpClient.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
		// 设置 连接超时时间
		httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(TIMEOUT_CONNECTION);
		// 设置 读数据超时时间
		httpClient.getHttpConnectionManager().getParams().setSoTimeout(TIMEOUT_SOCKET);
		// 设置 字符集
		httpClient.getParams().setContentCharset(UTF_8);
		return httpClient;
	}

	private static GetMethod getHttpGet(String url, String cookie, String userAgent) {
		GetMethod httpGet = new GetMethod(url);
		// 设置 请求超时时间
		httpGet.getParams().setSoTimeout(TIMEOUT_SOCKET);
		httpGet.setRequestHeader("Host", HOST);
		httpGet.setRequestHeader("Connection","Keep-Alive");
		httpGet.setRequestHeader("Cookie", cookie);
		httpGet.setRequestHeader("User-Agent", userAgent);
		return httpGet;
	}

	private static PostMethod getHttpPost(String url, String cookie, String userAgent) {
		PostMethod httpPost = new PostMethod(url);
		// 设置 请求超时时间
		httpPost.getParams().setSoTimeout(TIMEOUT_SOCKET);
		httpPost.setRequestHeader("Host", HOST);
		httpPost.setRequestHeader("Connection","Keep-Alive");
		httpPost.setRequestHeader("Cookie", cookie);
		httpPost.setRequestHeader("User-Agent", userAgent);
		return httpPost;
	}

    /**
	 * get请求URL
	 * @param url
	 */
	public static InputStream http_get(AppContext appContext, String url){
		//System.out.println("get_url==> "+url);
//		String cookie = getCookie(appContext);
		String userAgent = getUserAgent(appContext);

		HttpClient httpClient = null;
		GetMethod httpGet = null;

		String responseBody = "";
		int time = 0;
		do{
			try
			{
				httpClient = getHttpClient();
				httpGet = getHttpGet(url, "", userAgent);
				int statusCode = httpClient.executeMethod(httpGet);
				if (statusCode != HttpStatus.SC_OK) {
					Toast.makeText(AppContext.getAppContext(), "get"+AppContext.getAppContext().getResources().getString(R.string.url_return_code_err)+statusCode, Toast.LENGTH_LONG).show();
				}
				responseBody = httpGet.getResponseBodyAsString();
				//System.out.println("XMLDATA=====>"+responseBody);
				break;
			} catch (HttpException e) {
				time++;
				if(time < RETRY_TIME) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {}
					continue;
				}
				// 发生致命的异常，可能是协议不对或者返回的内容有问题
				e.printStackTrace();
				Toast.makeText(AppContext.getAppContext(), "get"+AppContext.getAppContext().getResources().getString(R.string.url_protocol_or_returndata_error), Toast.LENGTH_LONG).show();
			} catch (IOException e) {
				time++;
				if(time < RETRY_TIME) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {}
					continue;
				}
				// 发生网络异常
				e.printStackTrace();
				Toast.makeText(AppContext.getAppContext(), AppContext.getAppContext().getResources().getString(R.string.net_error), Toast.LENGTH_LONG).show();
			} finally {
				// 释放连接
				httpGet.releaseConnection();
				httpClient = null;
			}
		}while(time < RETRY_TIME);

		responseBody = responseBody.replace('', '?');

		return new ByteArrayInputStream(responseBody.getBytes());
	}

	/**
	 * 公用post方法
	 * @param url
	 * @param params
	 * @param files
	 */
	public static InputStream _post(AppContext appContext, String url, Map<String, Object> params, Map<String,File> files){
		//System.out.println("post_url==> "+url);
//		String cookie = getCookie(appContext);
		String userAgent = getUserAgent(appContext);

		HttpClient httpClient = null;
		PostMethod httpPost = null;

		//post表单参数处理
		int length = (params == null ? 0 : params.size()) + (files == null ? 0 : files.size());
		Part[] parts = new Part[length];
		int i = 0;
        if(params != null)
        for(String name : params.keySet()){
        	parts[i++] = new StringPart(name, String.valueOf(params.get(name)), UTF_8);
        	//System.out.println("post_key==> "+name+"    value==>"+String.valueOf(params.get(name)));
        }
        if(files != null)
        for(String file : files.keySet()){
        	try {
				parts[i++] = new FilePart(file, files.get(file));
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
        	//System.out.println("post_key_file==> "+file);
        }

		String responseBody = "";
		int time = 0;
		do{
			try
			{
				httpClient = getHttpClient();
				httpPost = getHttpPost(url, "", userAgent);
		        httpPost.setRequestEntity(new MultipartRequestEntity(parts,httpPost.getParams()));
		        int statusCode = httpClient.executeMethod(httpPost);
		        if(statusCode != HttpStatus.SC_OK)
		        {
		        	Toast.makeText(AppContext.getAppContext(), "post"+AppContext.getAppContext().getResources().getString(R.string.url_return_code_err)+statusCode, Toast.LENGTH_LONG).show();
		        }
		        //暂无cookie
//		        else if(statusCode == HttpStatus.SC_OK)
//		        {
//		            Cookie[] cookies = httpClient.getState().getCookies();
//		            String tmpcookies = "";
//		            for (Cookie ck : cookies) {
//		                tmpcookies += ck.toString()+";";
//		            }
//		            //保存cookie
//	        		if(appContext != null && tmpcookies != ""){
//	        			appContext.setProperty("cookie", tmpcookies);
//	        			appCookie = tmpcookies;
//	        		}
//		        }
		     	responseBody = httpPost.getResponseBodyAsString();
		        //System.out.println("XMLDATA=====>"+responseBody);
		     	break;
			} catch (HttpException e) {
				time++;
				if(time < RETRY_TIME) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {}
					continue;
				}
				// 发生致命的异常，可能是协议不对或者返回的内容有问题
				e.printStackTrace();
				Toast.makeText(AppContext.getAppContext(), "post"+AppContext.getAppContext().getResources().getString(R.string.url_protocol_or_returndata_error), Toast.LENGTH_LONG).show();
			} catch (IOException e) {
				time++;
				if(time < RETRY_TIME) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {}
					continue;
				}
				// 发生网络异常
				e.printStackTrace();
				Toast.makeText(AppContext.getAppContext(), AppContext.getAppContext().getResources().getString(R.string.net_error), Toast.LENGTH_LONG).show();
			} finally {
				// 释放连接
				httpPost.releaseConnection();
				httpClient = null;
			}
		}while(time < RETRY_TIME);

        responseBody = responseBody.replace('', '?');

        return new ByteArrayInputStream(responseBody.getBytes());
	}

}